home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / utils / xad / developer / sources / clients / dms.c next >
C/C++ Source or Header  |  1999-01-01  |  45KB  |  1,711 lines

  1. #ifndef XADMASTER_DMS_C
  2. #define XADMASTER_DMS_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        DMS.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: DMS.c 1.4 (04.03.1999)
  9.     Author:        SDI, Andre R. de la Rocha
  10.     Distribution:    Freeware
  11.     Description:    DMS and related disk/file archiver clients
  12.  
  13.  1.0   23.12.98 : first version
  14.  1.1   31.01.99 : added unpack stuff
  15.  1.2   04.02.99 : bug fixes, first full working version
  16.  1.3   16.02.99 : bug fixes
  17.  1.4   04.03.99 : added XADFIF_NODATE flag
  18. */
  19.  
  20. /* This format seems to have really lots of problems. Append option
  21. does not work correctly, because the crunching algorithm start data
  22. seems to be handled wrong. ENCRYPTION over APPEND borders doe not
  23. work correctly as well. DIZ text sometimes are encrypted, sometimes
  24. are not. Generally all is possible and all may fail. Hopefully there
  25. are not too much archives out there doing such a strange defective
  26. stuff. */
  27.  
  28. /* This client is lossely based (mainly decrunch stuff) on xDMS
  29. source made by Andre R. de la Rocha. Thanks for your work. The code
  30. has been made reentrant to fit requirements of shared libraries and
  31. also lots of strange files are handled correctly now. Crunch Type
  32. reinitialisation has been fixed as well. This client does not use
  33. DMS header information (except password flag), but always the track
  34. data. This should reduce influence of modified DMS files.
  35.  
  36. DIZ texts seem to use easy compression (NONE or RLE) always, so they
  37. can be decompressed without decompressiong all the data before.
  38. APPENDED files which use a password, where the normal file does
  39. not use one, will fail. The other way round should work.
  40. */
  41.  
  42. /* FMS format:
  43. - pre 2.04 FMS files contain file name in block DMSTRTYPE_FILENAME
  44. - 2.04 format contains additionally information:
  45.   LONGWORD    protection bits
  46.   3 LONGWORDs    DateStamp structure
  47.   UBYTE        size of following text, if bit 7 is set, the text
  48.         is a comment
  49. [ UBYTE        size of filename, when there was a comment]
  50. */
  51.  
  52. #include <proto/xadmaster.h>
  53. #include <proto/exec.h>
  54. #include <exec/memory.h>
  55. #include <dos/dos.h>
  56. #include <dos/doshunks.h>
  57. #include "SDI_compiler.h"
  58. #define SDI_TO_ANSI
  59. #include "SDI_ASM_STD_protos.h"
  60.  
  61. #ifndef XADMASTERFILE
  62. #define DMS_Client        FirstClient
  63. #define NEXTCLIENT        0
  64. UBYTE version[] = "$VER: DMS 1.4 (04.03.1999)";
  65. #endif
  66. #define DMS_VERSION        1
  67. #define DMS_REVISION        4
  68. #define DMSSFX_VERSION        DMS_VERSION
  69. #define DMSSFX_REVISION        DMS_REVISION
  70. #define SDSSFX_VERSION        DMS_VERSION
  71. #define SDSSFX_REVISION        DMS_REVISION
  72.  
  73. /****************************************************************************/
  74.  
  75. #define DMSINFO_NOZERO        (1<<0)
  76. #define DMSINFO_ENCRYPT        (1<<1)
  77. #define DMSINFO_APPENDS        (1<<2)
  78. #define DMSINFO_BANNER        (1<<3)
  79. #define DMSINFO_HIGHDENSITY    (1<<4)
  80. #define DMSINFO_PC        (1<<5)
  81. #define DMSINFO_DMS_DEVICE_FIX    (1<<6)
  82. #define DMSINFO_REGIST_VERSION    (1<<7)
  83. #define DMSINFO_DIZ        (1<<8)
  84. /* InfoFlags seem to be valid for first part. Appended part may have
  85.    other flags! */
  86.  
  87. #define DMSOSV_AMIGA_AGA    (1<<15)
  88.  
  89. #define DMSCPU_68000        0
  90. #define DMSCPU_68010        1
  91. #define DMSCPU_68020        2
  92. #define DMSCPU_68030        3
  93. #define DMSCPU_68040        4
  94. #define DMSCPU_68060        5
  95. #define DMSCPU_6086        6
  96. #define DMSCPU_8088        7
  97. #define DMSCPU_80188        8
  98. #define DMSCPU_80186        9
  99. #define DMSCPU_80286        10
  100. #define DMSCPU_80386SX        11
  101. #define DMSCPU_80386        12
  102. #define DMSCPU_80486        13
  103. #define DMSCPU_80586        14
  104.  
  105. #define DMSFPU_NONE        0
  106. #define DMSFPU_68881        1
  107. #define DMSFPU_68882        2
  108. #define DMSFPU_8087        3
  109. #define DMSFPU_80287SX        4
  110. #define DMSFPU_80387        5
  111.  
  112. #define DMSMACH_UNKNOWN        0
  113. #define DMSMACH_AMIGA        1
  114. #define DMSMACH_PC        2
  115. #define DMSMACH_ATARI        3
  116. #define DMSMACH_MACINTOSH    4
  117.  
  118. #define DMSTYPE_UNKNOWN        0
  119. #define DMSTYPE_AOS1OFS        1
  120. #define DMSTYPE_AOS1FFS        2
  121. #define DMSTYPE_AOS3INT        3
  122. #define DMSTYPE_AOS3INTFFS    4
  123. #define DMSTYPE_AOS3DIR        5
  124. #define DMSTYPE_AOS3DIRFFS    6
  125. #define DMSTYPE_FMS        7
  126.  
  127. #define DMSCOMP_NOCOMP        0
  128. #define DMSCOMP_SIMPLE        1
  129. #define DMSCOMP_QUICK        2
  130. #define DMSCOMP_MEDIUM        3
  131. #define DMSCOMP_DEEP        4
  132. #define DMSCOMP_HEAVY1        5
  133. #define DMSCOMP_HEAVY2        6
  134.  
  135. #define DMSCFLAG_NOINIT        (1<<0)
  136. #define DMSCFLAG_HEAVY_C    (1<<1)
  137. #define DMSCFLAG_HEAVYRLE    (1<<2)
  138. #define DMSCFLAG_HEAVY2        (1<<3)    /* own flag */
  139.  
  140. #define DMSTRTYPE_DIZ        80
  141. #define DMSTRTYPE_BANNER    -1
  142. #define DMSTRTYPE_FILENAME    0x03E7
  143. #define DMSTRTYPE_FILESTART    0x03E8
  144.  
  145. #define DMSPWD_USE    1
  146. #define DMSPWD_NOUSE    2
  147.  
  148. struct DMSHeader {
  149.   ULONG        DMSID;        /* "DMS!" */
  150.   ULONG        ID;        /* " PRO" or "FILE" */
  151.   ULONG        InfoFlags;    /* DMSINFO_ defines */
  152.   ULONG        Date;        /* UNIX format */
  153.   UWORD        LowTrack;
  154.   UWORD        HighTrack;
  155.   ULONG        PackedSize;
  156.   ULONG        UnpackedSize;
  157.   UWORD        OSVersion;    /* DMSOSV_ defines */
  158.   UWORD        OSRevision;
  159.   UWORD        CPU;        /* DMSCPU_ defines */
  160.   UWORD        FPU;        /* DMSFPU_ defines */
  161.   UWORD        Machine;    /* DMSMACH_ defines */
  162.   UWORD        DiskType2;    /* DMSTYPE_ defines */
  163.   UWORD        CPUSpeed;    /* multiplied (in 0.01 MHz) */
  164.   ULONG        CreationTime;
  165.   UWORD        CreatorVersion;
  166.   UWORD        NeededVersion;
  167.   UWORD        DiskType;    /* DMSTYPE_ defines */
  168.   UWORD        CompMode;    /* DMSCOMP_ defines */
  169.   UWORD        CheckSum;
  170.   /* checksums exclude DMSID and checksum word itself */
  171. };
  172.  
  173. struct DMSTrack {
  174.   UWORD        TRID;        /* "TR" */
  175.   WORD        TrackNumber;
  176.   UWORD        pad;
  177.   UWORD        CMODE_Packed;
  178.   UWORD        RuntimePacked;
  179.   UWORD        UnpackedSize;
  180.   UBYTE        CFlag;
  181.   UBYTE        CModeTrk;    /* DMSCOMP_ defines */
  182.   UWORD        UncrunchedCRC;
  183.   UWORD        CrunchedCRC;
  184.   UWORD        CheckSum;
  185. };
  186.  
  187. #define DMSNC 510
  188. #define DMSNPT 30
  189. #define DMSN1 510
  190. #define DMSOFFSET 253
  191.  
  192. #define DMSF        60        /* lookahead buffer size */
  193. #define DMSTHRESHOLD    2
  194. #define DMSN_BYTE    (256 - DMSTHRESHOLD + DMSF)    /* kinds of characters (character code = 0..DMSN_BYTE-1) */
  195. #define DMST        (DMSN_BYTE * 2 - 1)        /* size of table */
  196. #define DMSR        (DMST - 1)      /* position of root */
  197. #define DMSMAX_FREQ    0x8000          /* DMSupdates tree when the */
  198.  
  199. struct DMSData {
  200.   ULONG        bitbuf;
  201.   STRPTR    indata;
  202.   UBYTE        bitcount;
  203.   UBYTE        DidInit;
  204.   UWORD        RTV_Medium;
  205.   UBYTE        Text[32768];
  206.   /* the above are accessed by Medium decruncher and supplied as a short
  207.     data structure from SDS SFX */
  208.  
  209.   UWORD        UsePwd;
  210.   UWORD        PassCRC;
  211.   UWORD        RTV_Pass; /* RunTimeVariable */
  212.   UWORD        RTV_Quick;
  213.   UWORD        RTV_Deep;
  214.   UWORD        RTV_Heavy;
  215.   UWORD        c_table[4096];
  216.   UWORD        pt_table[256];
  217.   UWORD        lastlen;
  218.   UWORD        np;
  219.   UWORD        left[2*DMSNC - 1];
  220.   UWORD        right[2*DMSNC -1 + 9];
  221.   UWORD        freq[DMST + 1];        /* d->frequency table */
  222.   UWORD        prnt[DMST + DMSN_BYTE]; /* pointers to parent nodes, except for the */
  223.         /* elements [DMST..DMST + DMSN_BYTE - 1] which are used to get */
  224.         /* the positions of leaves corresponding to the codes. */
  225.   UWORD        son[DMST];    /* pointers to child nodes (son[], son[] + 1) */
  226.  
  227.   UBYTE        DidInitDEEP;
  228.   UBYTE        c_len[DMSNC];
  229.   UBYTE        pt_len[DMSNPT];
  230. };
  231.  
  232. struct DMSPos {
  233.   ULONG startpos;    /* decrunch start position */
  234.   ULONG firsttrack;    /* first decrunch track */
  235. };
  236.  
  237. /****************************************************************************/
  238.  
  239. static ULONG DMS_mask_bits[]={
  240.     0x000000,0x000001,0x000003,0x000007,0x00000f,0x00001f,
  241.     0x00003f,0x00007f,0x0000ff,0x0001ff,0x0003ff,0x0007ff,
  242.     0x000fff,0x001fff,0x003fff,0x007fff,0x00ffff,0x01ffff,
  243.     0x03ffff,0x07ffff,0x0fffff,0x1fffff,0x3fffff,0x7fffff,
  244.     0xffffff};
  245.  
  246. static UBYTE DMS_d_code[256] = {
  247.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  248.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  249.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  250.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  251.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  252.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  253.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  254.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  255.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  256.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  257.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  258.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  259.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  260.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  261.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  262.     0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  263.     0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
  264.     0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
  265.     0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
  266.     0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
  267.     0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
  268.     0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
  269.     0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
  270.     0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
  271.     0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
  272.     0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
  273.     0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
  274.     0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
  275.     0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
  276.     0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
  277.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  278.     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  279. };
  280.  
  281. static UBYTE DMS_d_len[256] = {
  282.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  283.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  284.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  285.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  286.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  287.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  288.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  289.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  290.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  291.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  292.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  293.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  294.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  295.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  296.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  297.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  298.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  299.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  300.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  301.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  302.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  303.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  304.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  305.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  306.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  307.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  308.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  309.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  310.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  311.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  312.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  313.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  314. };
  315.  
  316. /****************************************************************************/
  317.  
  318. static LONG DMSUnpRLE(STRPTR *res, ULONG size, struct ExecBase *SysBase)
  319. {
  320.   STRPTR out, outstore, outend, in = *res;
  321.   UWORD n;
  322.   UBYTE a,b;
  323.   LONG err = 0;
  324.  
  325.   if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
  326.     return XADERR_NOMEMORY;
  327.   
  328.   outend = out+size;
  329.  
  330.   while(out < outend && !err)
  331.   {
  332.     if((a = *(in++)) != 0x90)
  333.       *(out++) = a;
  334.     else if(!(b = *(in++)))
  335.       *(out++) = a;
  336.     else
  337.     {
  338.       a = *(in++);
  339.       if(b == 0xFF)
  340.       {
  341.         n = *(in++);
  342.         n = ((n<<8) + *(in++));
  343.       }
  344.       else
  345.         n = b;
  346.       if(out+n > outend)
  347.         err = XADERR_ILLEGALDATA;
  348.       else
  349.       {
  350.         memset(out,a,n);
  351.         out += n;
  352.       }
  353.     }
  354.   }
  355.  
  356.   FreeVec(*res);
  357.   *res = outstore;
  358.   return err;
  359. }
  360.  
  361. /****************************************************************************/
  362.  
  363. #define DMSGETBITS(n) ((UWORD)(d->bitbuf >> (d->bitcount-(n))))
  364. #define DMSDROPBITS(n) {d->bitbuf &= DMS_mask_bits[d->bitcount-=(n)]; \
  365.     while (d->bitcount<16) {d->bitbuf = (d->bitbuf << 8) | \
  366.     *d->indata++;  d->bitcount += 8;}}
  367.  
  368. static void DMSinitbitbuf(STRPTR in, struct DMSData *d)
  369. {
  370.   d->bitbuf = 0;
  371.   d->bitcount = 0;
  372.   d->indata = in;
  373.   DMSDROPBITS(0);
  374. }
  375.  
  376. static LONG DMSUnpQUICK(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
  377. {
  378.   STRPTR out, outstore, outend, in = *res;
  379.   UWORD i,j;
  380.   LONG err = 0;
  381.  
  382.   if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
  383.     return XADERR_NOMEMORY;
  384.  
  385.   d->DidInit = 0;    /* clear Init flag */
  386.  
  387.   DMSinitbitbuf(in, d);
  388.   outend = out + size;
  389.   while (out < outend)
  390.   {
  391.     if(DMSGETBITS(1))
  392.     {
  393.       DMSDROPBITS(1);
  394.       *out++ = d->Text[d->RTV_Quick++ & 0xFF] = (UBYTE) DMSGETBITS(8);
  395.       DMSDROPBITS(8);
  396.     }
  397.     else
  398.     {
  399.       DMSDROPBITS(1);
  400.       j = DMSGETBITS(2)+2;
  401.       DMSDROPBITS(2);
  402.       i = d->RTV_Quick - DMSGETBITS(8) - 1;
  403.       DMSDROPBITS(8);
  404.       if(j + out > outend)
  405.         err = XADERR_ILLEGALDATA;
  406.       else
  407.         while(j--)
  408.           *out++ = d->Text[d->RTV_Quick++ & 0xFF] = d->Text[i++ & 0xFF];
  409.     }
  410.   }
  411.   d->RTV_Quick = (d->RTV_Quick+5) & 0xFF;
  412.  
  413.   FreeVec(*res);
  414.   *res = outstore;
  415.   return err;
  416. }
  417.  
  418. /****************************************************************************/
  419.  
  420. static LONG DMSUnpMEDIUM(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
  421. {
  422.   STRPTR out, outstore, outend, in = *res;
  423.   UWORD i,j, c;
  424.   LONG err = 0;
  425.   UBYTE u;
  426.  
  427.   if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
  428.     return XADERR_NOMEMORY;
  429.  
  430.   d->DidInit = 0;    /* clear Init flag */
  431.  
  432.   DMSinitbitbuf(in, d);
  433.   outend = out + size;
  434.  
  435.   while(out < outend)
  436.   {
  437.     if(DMSGETBITS(1))
  438.     {
  439.       DMSDROPBITS(1);
  440.       *out++ = d->Text[d->RTV_Medium++ & 0x3FFF] = (UBYTE)DMSGETBITS(8);
  441.       DMSDROPBITS(8);
  442.     }
  443.     else
  444.     {
  445.       DMSDROPBITS(1);
  446.       c = DMSGETBITS(8);
  447.       DMSDROPBITS(8);
  448.       j = (UWORD) (DMS_d_code[c]+3);
  449.       u = DMS_d_len[c];
  450.       c = (UWORD) (((c << u) | DMSGETBITS(u)) & 0xff);
  451.       DMSDROPBITS(u);
  452.       u = DMS_d_len[c];
  453.       c = (UWORD) ((DMS_d_code[c] << 8) | (((c << u) | DMSGETBITS(u)) & 0xff));
  454.       DMSDROPBITS(u);
  455.       i = (UWORD) (d->RTV_Medium - c - 1);
  456.  
  457.       if(j + out > outend)
  458.         err = XADERR_ILLEGALDATA;
  459.       else
  460.         while(j--)
  461.           *out++ = d->Text[d->RTV_Medium++ & 0x3FFF] = d->Text[i++ & 0x3FFF];        
  462.     }
  463.   }
  464.   d->RTV_Medium = (UWORD)((d->RTV_Medium+66) & 0x3FFF);
  465.  
  466.   FreeVec(*res);
  467.   *res = outstore;
  468.   return err;
  469. }
  470.  
  471. /****************************************************************************/
  472.  
  473. /* reconstruction of tree */
  474. static void DMSreconst(struct DMSData *d)
  475. {
  476.   UWORD i, j, k, f, l;
  477.  
  478.   /* collect leaf nodes in the first half of the table */
  479.   /* and replace the d->freq by (d->freq + 1) / 2. */
  480.   j = 0;
  481.   for (i = 0; i < DMST; i++)
  482.   {
  483.     if(d->son[i] >= DMST)
  484.     {
  485.       d->freq[j] = (UWORD) ((d->freq[i] + 1) / 2);
  486.       d->son[j] = d->son[i];
  487.       j++;
  488.     }
  489.   }
  490.   /* begin constructing tree by connecting d->sons */
  491.   for(i = 0, j = DMSN_BYTE; j < DMST; i += 2, j++)
  492.   {
  493.     k = (UWORD) (i + 1);
  494.     f = d->freq[j] = (UWORD) (d->freq[i] + d->freq[k]);
  495.     for(k = (UWORD)(j - 1); f < d->freq[k]; k--)
  496.       ;
  497.     k++;
  498.     for(l = j; l > k; --l)
  499.     {
  500.       d->freq[l] = d->freq[l-1];
  501.       d->son[l] = d->son[l-1];
  502.     }
  503.     d->freq[k] = f;
  504.     d->son[k] = i;
  505.   }
  506.   /* connect d->prnt */
  507.   for(i = 0; i < DMST; i++)
  508.   {
  509.     if((k = d->son[i]) >= DMST)
  510.       d->prnt[k] = i;
  511.     else
  512.       d->prnt[k] = d->prnt[k + 1] = i;
  513.   }
  514. }
  515.  
  516. /* increment d->frequency of given code by one, and update tree */
  517. static void DMSupdate(UWORD c, struct DMSData *d)
  518. {
  519.   UWORD i, j, k, l;
  520.  
  521.   if(d->freq[DMSR] == DMSMAX_FREQ)
  522.     DMSreconst(d);
  523.   c = d->prnt[c + DMST];
  524.   do
  525.   {
  526.     k = ++d->freq[c];
  527.  
  528.     /* if the order is disturbed, exchange nodes */
  529.     if(k > d->freq[l = (UWORD)(c + 1)])
  530.     {
  531.       while(k > d->freq[++l])
  532.         ;
  533.       l--;
  534.       d->freq[c] = d->freq[l];
  535.       d->freq[l] = k;
  536.  
  537.       i = d->son[c];
  538.       d->prnt[i] = l;
  539.       if(i < DMST)
  540.         d->prnt[i + 1] = l;
  541.  
  542.       j = d->son[l];
  543.       d->son[l] = i;
  544.  
  545.       d->prnt[j] = c;
  546.       if(j < DMST)
  547.         d->prnt[j + 1] = c;
  548.       d->son[c] = j;
  549.  
  550.       c = l;
  551.     }
  552.   } while((c = d->prnt[c]) != 0); /* repeat up to root */
  553. }
  554.  
  555. static UWORD DMSDecodeChar(struct DMSData *d)
  556. {
  557.   UWORD c;
  558.  
  559.   c = d->son[DMSR];
  560.  
  561.   /* travel from root to leaf, */
  562.   /* choosing the smaller child node (d->son[]) if the read bit is 0, */
  563.   /* the bigger (d->son[]+1) if 1 */
  564.   while(c < DMST)
  565.   {
  566.     c = d->son[c + DMSGETBITS(1)];
  567.     DMSDROPBITS(1);
  568.   }
  569.   c -= DMST;
  570.   DMSupdate(c, d);
  571.   return c;
  572. }
  573.  
  574. static UWORD DMSDecodePosition(struct DMSData *d)
  575. {
  576.   UWORD i, j, c;
  577.  
  578.   i = DMSGETBITS(8);
  579.   DMSDROPBITS(8);
  580.   c = (UWORD) (DMS_d_code[i] << 8);
  581.   j = DMS_d_len[i];
  582.   i = (UWORD) (((i << j) | DMSGETBITS(j)) & 0xff);
  583.   DMSDROPBITS(j);
  584.  
  585.   return (UWORD) (c | i);
  586. }
  587.  
  588. static LONG DMSUnpDEEP(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
  589. {
  590.   STRPTR out, outstore, outend, in = *res;
  591.   UWORD i,j, c;
  592.   LONG err = 0;
  593.  
  594.   if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
  595.     return XADERR_NOMEMORY;
  596.  
  597.   d->DidInitDEEP = d->DidInit = 0;    /* clear Init flag */
  598.  
  599.   DMSinitbitbuf(in, d);
  600.   outend = out + size;
  601.  
  602.   while(out < outend)
  603.   {
  604.     c = DMSDecodeChar(d);
  605.     if(c < 256)
  606.       *out++ = d->Text[d->RTV_Deep++ & 0x3FFF] = (UBYTE)c;
  607.     else
  608.     {
  609.       j = (UWORD) (c - 255 + DMSTHRESHOLD);
  610.       i = (UWORD) (d->RTV_Deep - DMSDecodePosition(d) - 1);
  611.       if(j + out > outend)
  612.         err = XADERR_ILLEGALDATA;
  613.       else
  614.         while (j--)
  615.           *out++ = d->Text[d->RTV_Deep++ & 0x3FFF] = d->Text[i++ & 0x3FFF];
  616.     }
  617.   }
  618.  
  619.   d->RTV_Deep = (UWORD)((d->RTV_Deep+60) & 0x3FFF);
  620.  
  621.   FreeVec(*res);
  622.   *res = outstore;
  623.   return err;
  624. }
  625.  
  626. /****************************************************************************/
  627.  
  628. struct DMSTableData {
  629.   WORD        c;
  630.   UWORD        n;
  631.   UWORD        tblsiz;
  632.   UWORD        len;
  633.   UWORD        depth;
  634.   UWORD        maxdepth;
  635.   UWORD        avail;
  636.   UWORD        codeword;
  637.   UWORD        bit;
  638.   UWORD    *    tbl;
  639.   UWORD     TabErr;
  640.   STRPTR    blen;
  641.  
  642.   UWORD    *    left;  /* copy of data in DMSData */
  643.   UWORD    *    right; /* copy of data in DMSData */
  644. };
  645.  
  646. static UWORD DMSmktbl(struct DMSTableData *t)
  647. {
  648.   UWORD i=0;
  649.  
  650.   if(t->TabErr)
  651.     return 0;
  652.  
  653.   if(t->len == t->depth)
  654.   {
  655.     while(++t->c < t->n)
  656.       if(t->blen[t->c] == t->len)
  657.       {
  658.         i = t->codeword;
  659.         t->codeword += t->bit;
  660.         if(t->codeword > t->tblsiz)
  661.         {
  662.           t->TabErr=1;
  663.           return 0;
  664.         }
  665.         while(i < t->codeword)
  666.           t->tbl[i++] = (UWORD) t->c;
  667.         return (UWORD) t->c;
  668.       }
  669.       t->c = -1;
  670.       t->len++;
  671.       t->bit >>= 1;
  672.   }
  673.   t->depth++;
  674.   if(t->depth < t->maxdepth)
  675.   {
  676.     (void) DMSmktbl(t);
  677.     (void) DMSmktbl(t);
  678.   }
  679.   else if(t->depth > 32)
  680.   {
  681.     t->TabErr = 2;
  682.     return 0;
  683.   }
  684.   else
  685.   {
  686.     if((i = t->avail++) >= 2 * t->n - 1)
  687.     {
  688.       t->TabErr = 3;
  689.       return 0;
  690.     }
  691.     t->left[i] = DMSmktbl(t);
  692.     t->right[i] = DMSmktbl(t);
  693.     if(t->codeword >= t->tblsiz)
  694.     {
  695.       t->TabErr = 4;
  696.       return 0;
  697.     }
  698.     if(t->depth == t->maxdepth)
  699.       t->tbl[t->codeword++] = i;
  700.   }
  701.   t->depth--;
  702.   return i;
  703. }
  704.  
  705. static UWORD DMSmake_table(UWORD nchar, UBYTE bitlen[], UWORD tablebits, UWORD table[],
  706. struct DMSData *d)
  707. {
  708.   struct DMSTableData t;
  709.  
  710.   t.left = d->left;
  711.   t.right = d->right;
  712.  
  713.   t.n = t.avail = nchar;
  714.   t.blen = bitlen;
  715.   t.tbl = table;
  716.   t.tblsiz = (UWORD) (1 << tablebits);
  717.   t.bit = (UWORD) (t.tblsiz / 2);
  718.   t.maxdepth = (UWORD)(tablebits + 1);
  719.   t.depth = t.len = 1;
  720.   t.c = -1;
  721.   t.codeword = 0;
  722.   t.TabErr = 0;
  723.   (void) DMSmktbl(&t);    /* left subtree */
  724.   (void) DMSmktbl(&t);    /* right subtree */
  725.   if(t.TabErr)
  726.     return t.TabErr;
  727.   if(t.codeword != t.tblsiz)
  728.     return 5;
  729.   return 0;
  730. }
  731.  
  732. static UWORD DMSdecode_c(struct DMSData *d)
  733. {
  734.   UWORD i, j, m;
  735.  
  736.   j = d->c_table[DMSGETBITS(12)];
  737.   if(j < DMSN1)
  738.   {
  739.     DMSDROPBITS(d->c_len[j]);
  740.   }
  741.   else
  742.   {
  743.     DMSDROPBITS(12);
  744.     i = DMSGETBITS(16);
  745.     m = 0x8000;
  746.     do
  747.     {
  748.       if(i & m)
  749.         j = d->right[j];
  750.       else
  751.         j = d->left[j];
  752.       m >>= 1;
  753.     } while (j >= DMSN1);
  754.     DMSDROPBITS(d->c_len[j] - 12);
  755.   }
  756.   return j;
  757. }
  758.  
  759. static UWORD DMSdecode_p(struct DMSData *d)
  760. {
  761.   UWORD i, j, m;
  762.  
  763.   j = d->pt_table[DMSGETBITS(8)];
  764.   if(j < d->np)
  765.   {
  766.     DMSDROPBITS(d->pt_len[j]);
  767.   }
  768.   else
  769.   {
  770.     DMSDROPBITS(8);
  771.     i = DMSGETBITS(16);
  772.     m = 0x8000;
  773.     do
  774.     {
  775.       if(i & m)
  776.         j = d->right[j];
  777.       else
  778.         j = d->left[j];
  779.       m >>= 1;
  780.     } while (j >= d->np);
  781.     DMSDROPBITS(d->pt_len[j] - 8);
  782.   }
  783.  
  784.   if(j != d->np-1)
  785.   {
  786.     if(j > 0)
  787.     {
  788.       j = (UWORD)(DMSGETBITS(i=(UWORD)(j-1)) | (1 << (j-1)));
  789.       DMSDROPBITS(i);
  790.     }
  791.     d->lastlen=j;
  792.   }
  793.  
  794.   return d->lastlen;
  795. }
  796.  
  797. static UWORD DMSread_tree_c(struct DMSData *d)
  798. {
  799.   UWORD i,n;
  800.  
  801.   n = DMSGETBITS(9);
  802.   DMSDROPBITS(9);
  803.   if(n > 0)
  804.   {
  805.     for(i=0; i<n; i++)
  806.     {
  807.       d->c_len[i] = (UBYTE)DMSGETBITS(5);
  808.       DMSDROPBITS(5);
  809.     }
  810.     for(i=n; i<510; i++)
  811.       d->c_len[i] = 0;
  812.     if(DMSmake_table(510,d->c_len,12,d->c_table, d))
  813.       return 1;
  814.   }
  815.   else
  816.   {
  817.     n = DMSGETBITS(9);
  818.     DMSDROPBITS(9);
  819.     for(i=0; i<510; i++)
  820.       d->c_len[i] = 0;
  821.     for(i=0; i<4096; i++)
  822.       d->c_table[i] = n;
  823.   }
  824.   return 0;
  825. }
  826.  
  827. static UWORD DMSread_tree_p(struct DMSData *d)
  828. {
  829.   UWORD i,n;
  830.  
  831.   n = DMSGETBITS(5);
  832.   DMSDROPBITS(5);
  833.   if(n > 0)
  834.   {
  835.     for(i=0; i<n; i++)
  836.     {
  837.       d->pt_len[i] = (UBYTE) DMSGETBITS(4);
  838.       DMSDROPBITS(4);
  839.     }
  840.     for(i=n; i<d->np; i++)
  841.     d->pt_len[i] = 0;
  842.     if(DMSmake_table(d->np,d->pt_len,8,d->pt_table, d))
  843.       return 1;
  844.   }
  845.   else
  846.   {
  847.     n = DMSGETBITS(5);
  848.     DMSDROPBITS(5);
  849.     for(i=0; i<d->np; i++)
  850.       d->pt_len[i] = 0;
  851.     for (i=0; i<256; i++)
  852.       d->pt_table[i] = n;
  853.   }
  854.   return 0;
  855. }
  856.  
  857. static LONG DMSUnpHEAVY(STRPTR *res, ULONG size, UBYTE flags, struct DMSData *d, struct ExecBase *SysBase)
  858. {
  859.   STRPTR out, outstore, outend, in = *res;
  860.   UWORD i,j, c, bitmask;
  861.   LONG err = 0;
  862.  
  863.   if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
  864.     return XADERR_NOMEMORY;
  865.  
  866.   d->DidInit = 0;    /* clear Init flag */
  867.  
  868.   /*  Heavy 1 uses a 4Kb dictionary,  Heavy 2 uses 8Kb  */
  869.  
  870.   if(flags & DMSCFLAG_HEAVY2)
  871.   {
  872.     d->np = 15;
  873.     bitmask = 0x1fff;
  874.   }
  875.   else
  876.   {
  877.     d->np = 14;
  878.     bitmask = 0x0fff;
  879.   }
  880.  
  881.   DMSinitbitbuf(in, d);
  882.   outend = out + size;
  883.  
  884.  
  885.   if(flags & DMSCFLAG_HEAVY_C)
  886.   {
  887.     if(DMSread_tree_c(d))
  888.       return 1;
  889.     if(DMSread_tree_p(d))
  890.       return 2;
  891.   }
  892.  
  893.   while(out < outend)
  894.   {
  895.     c = DMSdecode_c(d);
  896.     if(c < 256)
  897.       *out++ = d->Text[d->RTV_Heavy++ & bitmask] = (UBYTE)c;
  898.     else
  899.     {
  900.       j = (UWORD) (c - DMSOFFSET);
  901.       i = (UWORD) (d->RTV_Heavy - DMSdecode_p(d) - 1);
  902.       if(j + out > outend)
  903.         err = XADERR_ILLEGALDATA;
  904.       else
  905.         while(j--)
  906.           *out++ = d->Text[d->RTV_Heavy++ & bitmask] = d->Text[i++ & bitmask];
  907.     }
  908.   }
  909.  
  910.   FreeVec(*res);
  911.   *res = outstore;
  912.   return err;
  913.  
  914. }
  915.  
  916. /****************************************************************************/
  917. /*  track 80 is FILEID.DIZ, track 0xffff (-1) is Banner  */
  918. /*  and track 0 with 1024 bytes only is a fake boot block with more advertising */
  919.  
  920. static LONG testDMSTrack(struct DMSTrack *t, struct xadMasterBase *xadMasterBase)
  921. {
  922.   if(t->TRID != 0x5452)
  923.     return XADERR_ILLEGALDATA;
  924.   if(xadCalcCRC16(XADCRC16_ID1, 0, sizeof(struct DMSTrack)-2,
  925.   (STRPTR)t) != t->CheckSum)
  926.     return XADERR_CHECKSUM;
  927.  
  928.   return 0;
  929. }
  930.  
  931. static UWORD CheckSumDMS(STRPTR mem, ULONG size)
  932. {
  933.   UWORD u = 0;
  934.  
  935.   while(size--)
  936.     u += *mem++;
  937.  
  938.   return u;
  939. }
  940.  
  941. static void DecryptDMS(STRPTR p, ULONG size, struct DMSData *d)
  942. {
  943.   UWORD t;
  944.  
  945.   while(size--)
  946.   {
  947.     t = (UWORD) *p;
  948.     *p++ ^= (UBYTE) d->RTV_Pass;
  949.     d->RTV_Pass = (UWORD)((d->RTV_Pass >> 1) + t);
  950.   }
  951. }
  952.  
  953. static void DMSInitData(struct DMSData *d)
  954. {
  955.   d->RTV_Quick = 251;
  956.   d->RTV_Medium = 0x3FBE;
  957.   d->RTV_Deep = 0x3fc4;
  958.  
  959.   if(!d->DidInitDEEP)
  960.   {
  961.     UWORD i, j;
  962.     for(i = 0; i < DMSN_BYTE; i++)
  963.     {
  964.       d->freq[i] = 1;
  965.       d->son[i] = (UWORD)(i + DMST);
  966.       d->prnt[i + DMST] = i;
  967.     }
  968.     i = 0;
  969.     j = DMSN_BYTE;
  970.     while(j <= DMSR)
  971.     {
  972.       d->freq[j] = (UWORD) (d->freq[i] + d->freq[i + 1]);
  973.       d->son[j] = i;
  974.       d->prnt[i] = d->prnt[i + 1] = j;
  975.       i += 2;
  976.       j++;
  977.     }
  978.     d->freq[DMST] = 0xffff;
  979.     d->prnt[DMSR] = 0;
  980.   }
  981.  
  982.   d->DidInit = d->DidInitDEEP = 1;
  983.  
  984.   memset(d->Text,0,0x3fc8);
  985. }
  986.  
  987. /* always make buffer 1 byte larger, which is filled with 0! */
  988. static LONG DecrunchDMS(struct DMSTrack *t, struct xadArchiveInfo *ai,
  989. struct xadMasterBase *xadMasterBase, STRPTR *res, struct DMSData *d)
  990. {
  991.   APTR inbuf;
  992.   LONG err;
  993.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  994.  
  995.   *res = 0;
  996.  
  997.   if(!(inbuf = AllocVec(t->CMODE_Packed+1, MEMF_PUBLIC|MEMF_CLEAR)))
  998.     return XADERR_NOMEMORY;
  999.  
  1000.   if((err = xadHookAccess(XADAC_READ, t->CMODE_Packed, inbuf, ai)))
  1001.   {
  1002.     FreeVec(inbuf);
  1003.     return err;
  1004.   }
  1005.  
  1006.   *res = inbuf;
  1007.  
  1008.   if(d->UsePwd == DMSPWD_USE && d->PassCRC)
  1009.     DecryptDMS(inbuf, t->CMODE_Packed, d);
  1010.  
  1011.   switch(t->CModeTrk)
  1012.   {
  1013.   case DMSCOMP_NOCOMP: break;
  1014.   case DMSCOMP_SIMPLE: err = DMSUnpRLE(res, t->UnpackedSize, SysBase); break;
  1015.   case DMSCOMP_QUICK:
  1016.     if(!(err = DMSUnpQUICK(res, t->RuntimePacked, d, SysBase)))
  1017.       err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
  1018.     break;
  1019.   case DMSCOMP_MEDIUM:
  1020.     if(!(err = DMSUnpMEDIUM(res, t->RuntimePacked, d, SysBase)))
  1021.       err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
  1022.     break;
  1023.   case DMSCOMP_DEEP:
  1024.     if(!(err = DMSUnpDEEP(res, t->RuntimePacked, d, SysBase)))
  1025.       err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
  1026.     break;
  1027.   case DMSCOMP_HEAVY1: case DMSCOMP_HEAVY2:
  1028.     if(t->CModeTrk == DMSCOMP_HEAVY1)
  1029.       err = DMSUnpHEAVY(res, t->RuntimePacked, t->CFlag & ~DMSCFLAG_HEAVY2, d, SysBase);
  1030.     else
  1031.       err = DMSUnpHEAVY(res, t->RuntimePacked, t->CFlag | DMSCFLAG_HEAVY2, d, SysBase);
  1032.     if(t->CFlag & DMSCFLAG_HEAVYRLE && !err)
  1033.       err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
  1034.     break;
  1035.   default: err = XADERR_DECRUNCH; break;
  1036.   }
  1037.  
  1038.   if(!err && CheckSumDMS(*res, t->UnpackedSize) != t->UncrunchedCRC)
  1039.   {
  1040.     /* try again without password */
  1041.     if(d->UsePwd == DMSPWD_USE && d->PassCRC && !(err = xadHookAccess(XADAC_INPUTSEEK,
  1042.     -t->CMODE_Packed, 0, ai)))
  1043.     {
  1044.       FreeVec(*res);
  1045.       d->UsePwd = DMSPWD_NOUSE;
  1046.       return DecrunchDMS(t, ai, xadMasterBase, res, d);
  1047.     }
  1048.     if(!err)
  1049.       err = d->UsePwd ? XADERR_PASSWORD : XADERR_CHECKSUM;
  1050.   }
  1051.  
  1052.   if(!(t->CFlag & DMSCFLAG_NOINIT) && !(d->DidInit))
  1053.     DMSInitData(d);
  1054.  
  1055.   if(err)
  1056.   {
  1057.     if(*res)
  1058.     {
  1059.       FreeVec(*res);
  1060.       *res= 0;
  1061.     }
  1062.   }
  1063.  
  1064.   return err;
  1065. }
  1066.  
  1067. static struct DMSData *GetDMSData(struct xadMasterBase *xadMasterBase, STRPTR pwd)
  1068. {
  1069.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1070.   struct DMSData *d;
  1071.   if((d = (struct DMSData *) AllocVec(sizeof(struct DMSData), MEMF_CLEAR)))
  1072.   {
  1073.     DMSInitData(d);
  1074.     if(pwd)
  1075.       d->RTV_Pass = d->PassCRC = xadCalcCRC16(XADCRC16_ID1, 0, strlen(pwd), pwd);
  1076.   }
  1077.   return d;
  1078. }
  1079.  
  1080. /****************************************************************************/
  1081.  
  1082. ASM(BOOL) DMS_RecogData(REG(d0, ULONG size), REG(a0, struct DMSHeader *h),
  1083. REG(a6, struct xadMasterBase *xadMasterBase))
  1084. {
  1085.   if(h->DMSID == 0x444D5321 && xadCalcCRC16(XADCRC16_ID1, 0,
  1086.   sizeof(struct DMSHeader)-6, ((STRPTR)h)+4) == h->CheckSum)
  1087.     return 1;
  1088.   else
  1089.     return 0;
  1090. }
  1091.  
  1092. /****************************************************************************/
  1093.  
  1094. /* Only the crypted information is used form DMS header. All the other
  1095.    information is taken from data directly, to allow these lots of
  1096.    modified headers. */
  1097.  
  1098. static struct xadDiskInfo *DMSOneArc(struct xadMasterBase *xadMasterBase,
  1099. struct xadArchiveInfo *ai, LONG *more, LONG crypted, LONG *ret)
  1100. {
  1101.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1102.   struct xadDiskInfo *di;
  1103.   struct xadTextInfo *ti = 0, *ti2;
  1104.   struct DMSData *d;
  1105.   struct DMSTrack t;
  1106.   LONG err = 0, stop = 0, tracksize = 0;
  1107.   LONG lowcyl = -1, highcyl = -1;
  1108.   STRPTR zerotxt = 0;
  1109.   ULONG zerosize = 0;
  1110.  
  1111.   *more = 0;
  1112.  
  1113.   if((di = (struct xadDiskInfo *) xadAllocObject(XADOBJ_DISKINFO,
  1114.   XAD_OBJPRIVINFOSIZE, sizeof(struct DMSPos), TAG_DONE)))
  1115.   {
  1116.     struct DMSPos *dpos;
  1117.  
  1118.     dpos = (struct DMSPos *) (di->xdi_PrivateInfo);
  1119.     if((d = GetDMSData(xadMasterBase, ai->xai_Password)))
  1120.     {
  1121.       if(crypted)
  1122.         d->UsePwd = DMSPWD_USE;
  1123.  
  1124.       dpos->startpos = ai->xai_InPos;
  1125.  
  1126.       while(!stop && !err)
  1127.       {
  1128.         if(xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai))
  1129.           stop = 1;
  1130.         else
  1131.         {
  1132.           if(testDMSTrack(&t, xadMasterBase))
  1133.         stop = 2;    /* stop > 1 means seek back one Track */
  1134.           else
  1135.           {
  1136.             if(zerotxt)
  1137.             {
  1138.               while(zerosize && !zerotxt[zerosize-1])
  1139.                 --zerosize;
  1140.               if(t.TrackNumber != 1 && zerosize && zerosize <= 2048) /* was a information text */
  1141.               {
  1142.         highcyl = lowcyl = -1; /* reset these two */
  1143.                 if((ti2 = (struct xadTextInfo *) xadAllocObjectA(XADOBJ_TEXTINFO, 0)))
  1144.                 {
  1145.               if(ti)
  1146.             ti->xti_Next = ti2;
  1147.           else
  1148.             di->xdi_TextInfo = ti2;
  1149.           ti = ti2;
  1150.           if(!(ti2->xti_Text = (STRPTR) AllocVec(zerosize+1, MEMF_PUBLIC|MEMF_CLEAR)))
  1151.             err = XADERR_NOMEMORY;
  1152.           else
  1153.           {
  1154.             ti2->xti_Size = zerosize;
  1155.             CopyMem(zerotxt, ti->xti_Text, zerosize);
  1156.           }
  1157.             }
  1158.             else
  1159.               err = XADERR_NOMEMORY;
  1160.               }
  1161.               FreeVec(zerotxt);
  1162.               zerotxt = 0;
  1163.             }
  1164.             /* Normally only -1 is allowed as banner, but I found at least
  1165.                one file using -2. */
  1166.             if(t.TrackNumber < 0 || t.TrackNumber == DMSTRTYPE_DIZ ||
  1167.             (!t.TrackNumber && t.UnpackedSize == 1024))
  1168.             {
  1169.               if((ti2 = (struct xadTextInfo *) xadAllocObjectA(XADOBJ_TEXTINFO, 0)))
  1170.               {
  1171.                 if(t.TrackNumber == DMSTRTYPE_DIZ)
  1172.                   ti2->xti_Flags |= XADTIF_FILEDIZ;
  1173.         if(!DecrunchDMS(&t, ai, xadMasterBase, &ti2->xti_Text, d))
  1174.           ti2->xti_Size = t.UnpackedSize;
  1175.         else if(crypted && !d->PassCRC)
  1176.           ti2->xti_Flags |= XADTIF_CRYPTED;
  1177.         if(ti)
  1178.           ti->xti_Next = ti2;
  1179.         else
  1180.           di->xdi_TextInfo = ti2;
  1181.         ti = ti2;
  1182.           }
  1183.           else
  1184.             err = XADERR_NOMEMORY;
  1185.         }
  1186.         else
  1187.         {
  1188.           if(highcyl == -1)
  1189.           {
  1190.             highcyl = lowcyl = t.TrackNumber;
  1191.             tracksize = t.UnpackedSize;
  1192.         dpos->firsttrack = ai->xai_InPos-sizeof(struct DMSTrack);
  1193.         if(!t.TrackNumber)
  1194.         {
  1195.           zerosize = t.UnpackedSize;
  1196.           if((DecrunchDMS(&t, ai, xadMasterBase, &zerotxt, d)))
  1197.             zerotxt = 0;    /* ignore it */
  1198.           continue;
  1199.         }
  1200.           }
  1201.           else if(t.TrackNumber != highcyl+1 || tracksize != t.UnpackedSize)
  1202.           {
  1203.             stop = 3; break;
  1204.           }
  1205.           else
  1206.             ++highcyl;
  1207.  
  1208.               if(d->UsePwd)
  1209.               {
  1210.             STRPTR a;
  1211.             if(!(a = AllocMem(t.CMODE_Packed, MEMF_ANY)))
  1212.               err = XADERR_NOMEMORY;
  1213.             else
  1214.             {
  1215.               if(!(err = xadHookAccess(XADAC_READ, t.CMODE_Packed, a, ai)))
  1216.                 DecryptDMS(a, t.CMODE_Packed, d);    /* to get a valid pwd pointer */
  1217.               FreeMem(a, t.CMODE_Packed);
  1218.             }
  1219.               }
  1220.               else
  1221.                 err = xadHookAccess(XADAC_INPUTSEEK, t.CMODE_Packed, 0, ai);
  1222.             }
  1223.           } /* testDMSTrack */
  1224.         } /* xadHookAccess */
  1225.       } /* while */
  1226.  
  1227.       if(zerotxt) /* in case there is only one zero track and nothing else */
  1228.       {
  1229.         FreeVec(zerotxt);
  1230.         zerotxt = 0;
  1231.       }
  1232.  
  1233.       if(stop > 1)
  1234.         err = xadHookAccess(XADAC_INPUTSEEK, -sizeof(struct DMSTrack), &t, ai);
  1235.  
  1236.       if(!tracksize || lowcyl == -1 || highcyl == -1 || tracksize % (2*512))
  1237.         err = XADERR_ILLEGALDATA;
  1238.       else
  1239.       {
  1240.     if(crypted & DMSINFO_ENCRYPT)
  1241.       di->xdi_Flags = XADDIF_CRYPTED;
  1242.  
  1243.     tracksize /= (2*512);
  1244.  
  1245.     di->xdi_LowCyl = lowcyl;
  1246.     di->xdi_HighCyl = highcyl;
  1247.     di->xdi_SectorSize = 512;
  1248.     di->xdi_Heads = 2;
  1249.     di->xdi_Cylinders = 80;
  1250.         switch(tracksize)
  1251.         {
  1252.         case 18: case 9:
  1253.           di->xdi_EntryInfo = "MSDOS disk"; /* no break! */
  1254.     case 22: case 11:
  1255.       di->xdi_TrackSectors = tracksize;
  1256.       break;
  1257.         default: err = XADERR_ILLEGALDATA; break;
  1258.     }
  1259.     di->xdi_CylSectors = 2 * di->xdi_TrackSectors;
  1260.     di->xdi_TotalSectors = 80 * di->xdi_CylSectors;
  1261.       }
  1262.  
  1263.       FreeVec(d);
  1264.     } /* GetDMSData */
  1265.     else
  1266.       err = XADERR_NOMEMORY;
  1267.  
  1268.     if(err)
  1269.     {
  1270.       for(ti = di->xdi_TextInfo; ti; ti = ti2)
  1271.       {
  1272.         ti2 = ti->xti_Next;
  1273.         if(ti->xti_Text)
  1274.           FreeVec(ti->xti_Text);
  1275.         xadFreeObjectA(ti, 0);
  1276.       }
  1277.       xadFreeObjectA(di, 0);
  1278.       di = 0;
  1279.     }
  1280.   } /* xadAllocObjectA */
  1281.   else
  1282.     err = XADERR_NOMEMORY;
  1283.  
  1284.   *ret = err;
  1285.   if(stop == 3 && !err)
  1286.     *more = 1;
  1287.  
  1288.   return di;
  1289. }
  1290.  
  1291. ASM(LONG) DMS_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  1292. REG(a6, struct xadMasterBase *xadMasterBase))
  1293. {
  1294.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1295.   LONG err = 0;
  1296.   struct DMSHeader h;
  1297.   struct DMSTrack t = {0};
  1298.   struct xadFileInfo *fi = 0, *fi2;
  1299.   struct xadDiskInfo *di = 0, *di2;
  1300.   ULONG num = 1, i, j;
  1301.  
  1302.   /* appended stuff is treated as own archive, as there may be gaps and double
  1303.      parts due to the chaotic file format of DMS. */
  1304.  
  1305.   while(!err && !xadHookAccess(XADAC_READ, sizeof(struct DMSHeader), &h, ai))
  1306.   {
  1307.     if(!testDMSTrack((struct DMSTrack *) &h, xadMasterBase))
  1308.       err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct DMSTrack)+
  1309.       sizeof(struct DMSHeader)+((struct DMSTrack *)&h)->CMODE_Packed, 0, ai);
  1310.     else
  1311.     {
  1312.       if(!DMS_RecogData(sizeof(struct DMSHeader), &h, xadMasterBase))
  1313.         return 0;
  1314.  
  1315.       if(h.InfoFlags & DMSINFO_ENCRYPT)
  1316.         ai->xai_Flags |= XADAIF_CRYPTED;
  1317.       if(h.DiskType2 == DMSTYPE_FMS || h.DiskType == DMSTYPE_FMS)
  1318.       {
  1319.         if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
  1320.         !(err = testDMSTrack(&t, xadMasterBase)) && t.TrackNumber == DMSTRTYPE_FILENAME)
  1321.         {
  1322.           if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  1323.           XAD_OBJNAMESIZE, t.UnpackedSize+1, TAG_DONE)))
  1324.             return XADERR_NOMEMORY;
  1325.           if(!(err = xadHookAccess(XADAC_READ, t.UnpackedSize, fi2->xfi_FileName, ai)))
  1326.           {
  1327.             i = ai->xai_InPos;
  1328.             j = 0;
  1329.             while(j < h.UnpackedSize && !err)
  1330.             {
  1331.               if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
  1332.               !(err = testDMSTrack(&t, xadMasterBase)))
  1333.               {
  1334.                 if(!(err = xadHookAccess(XADAC_INPUTSEEK, t.CMODE_Packed, 0, ai)))
  1335.                   j += t.UnpackedSize;
  1336.               }
  1337.             }
  1338.             if(!err)
  1339.             {
  1340.           if(h.InfoFlags & DMSINFO_ENCRYPT)
  1341.             fi2->xfi_Flags = XADFIF_CRYPTED;
  1342.               h.Date -= 7*60*60;
  1343.           if(!fi2->xfi_FileName[0]) /* This is a 2.04 FMS files */
  1344.           {
  1345.             struct FMSInfo {
  1346.               LONG prot;
  1347.               struct DateStamp d;
  1348.               } inf;
  1349.  
  1350.         CopyMem(fi2->xfi_FileName, &inf, sizeof(struct FMSInfo));
  1351.         fi2->xfi_FileName += sizeof(struct FMSInfo);
  1352.           
  1353.             fi2->xfi_Protection = inf.prot;
  1354.                 err = xadConvertDates(XAD_DATEDATESTAMP, &inf.d,
  1355.                 XAD_GETDATEXADDATE, &fi2->xfi_Date, TAG_DONE);
  1356.             if(fi2->xfi_FileName[0] & 0x80)
  1357.             {
  1358.               fi2->xfi_Comment = fi2->xfi_FileName+1;
  1359.               fi2->xfi_FileName += (fi2->xfi_FileName[0]&0x7F)+1;
  1360.             }
  1361.             *(fi2->xfi_FileName++) = 0; /* clear size (make C pointer) */
  1362.           }
  1363.           else
  1364.                 err = xadConvertDates(XAD_DATEUNIX, h.Date,
  1365.                 XAD_GETDATEXADDATE, &fi2->xfi_Date, XAD_MAKELOCALDATE, 1, TAG_DONE);
  1366.               fi2->xfi_PrivateInfo = (APTR) i;
  1367.               fi2->xfi_EntryNumber = num++;
  1368.               fi2->xfi_Size = h.UnpackedSize;
  1369.               fi2->xfi_CrunchSize = h.PackedSize;
  1370.               if(fi)
  1371.                 fi->xfi_Next = fi2;
  1372.               else
  1373.                 ai->xai_FileInfo = fi2;
  1374.               fi = fi2;
  1375.               fi2 = 0;
  1376.             }
  1377.           }
  1378.           if(fi2)
  1379.             xadFreeObjectA(fi2, 0);
  1380.         }
  1381.       }
  1382.       else /* is a disk archive */
  1383.       {
  1384.     LONG more = 1;
  1385.     
  1386.     while(more)
  1387.     {
  1388.       if((di2 = DMSOneArc(xadMasterBase, ai, &more, h.InfoFlags & DMSINFO_ENCRYPT, &err)))
  1389.       {
  1390.         di2->xdi_EntryNumber = num++;
  1391.             if(di)
  1392.               di->xdi_Next = di2;
  1393.             else
  1394.               ai->xai_DiskInfo = di2;
  1395.             di = di2;
  1396.       }
  1397.     }
  1398.       } /* DISK ARCHIVE */
  1399.     } /* found correct track */
  1400.     if(err)
  1401.       ai->xai_Flags |= XADAIF_FILECORRUPT;
  1402.   } /* while */
  1403.  
  1404.   return 0;
  1405. }
  1406.  
  1407. /****************************************************************************/
  1408.  
  1409. ASM(LONG) DMS_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  1410. REG(a6, struct xadMasterBase *xadMasterBase))
  1411. {
  1412.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1413.   struct DMSTrack t;
  1414.   LONG i;
  1415.   LONG err = 0;
  1416.   STRPTR pwd = ai->xai_Password;
  1417.   struct DMSData *d;
  1418.  
  1419.   if((ai->xai_CurFile && !(ai->xai_CurFile->xfi_Flags & XADFIF_CRYPTED)) ||
  1420.   !(ai->xai_CurDisk->xdi_Flags & XADDIF_CRYPTED))
  1421.     pwd = 0;
  1422.   else if(!pwd)
  1423.     return XADERR_PASSWORD;
  1424.  
  1425.   if(!(d = GetDMSData(xadMasterBase, pwd)))
  1426.     return XADERR_NOMEMORY;  
  1427.  
  1428.   if(ai->xai_CurFile)
  1429.   {
  1430.     struct xadFileInfo *fi;
  1431.  
  1432.     fi = ai->xai_CurFile;
  1433.  
  1434.     if(fi->xfi_Flags & XADFIF_CRYPTED)
  1435.       d->UsePwd = DMSPWD_USE;
  1436.  
  1437.     if(ai->xai_InPos != (ULONG) fi->xfi_PrivateInfo)
  1438.       err = xadHookAccess(XADAC_INPUTSEEK, ((ULONG) fi->xfi_PrivateInfo) - ai->xai_InPos, 0, ai);
  1439.  
  1440.     for(i = DMSTRTYPE_FILESTART; !err && ai->xai_OutSize < fi->xfi_Size; ++i)
  1441.     {
  1442.       if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
  1443.       !(err = testDMSTrack(&t, xadMasterBase)))
  1444.       {
  1445.         STRPTR res;
  1446.  
  1447.         if(i != t.TrackNumber)
  1448.           err = XADERR_ILLEGALDATA;
  1449.         else if(!(err = DecrunchDMS(&t, ai, xadMasterBase, &res, d)))
  1450.         {
  1451.           err = xadHookAccess(XADAC_WRITE, t.UnpackedSize, res, ai);
  1452.           FreeVec(res);
  1453.         }
  1454.       }
  1455.     }
  1456.   }
  1457.   else
  1458.   {
  1459.     struct xadDiskInfo *di;
  1460.     struct DMSPos *dpos;
  1461.  
  1462.     di = ai->xai_CurDisk;
  1463.     dpos = (struct DMSPos *) (di->xdi_PrivateInfo);
  1464.  
  1465.     if(di->xdi_Flags & XADDIF_CRYPTED)
  1466.       d->UsePwd = DMSPWD_USE;
  1467.  
  1468.     if(ai->xai_InPos != dpos->startpos)
  1469.       err = xadHookAccess(XADAC_INPUTSEEK, dpos->startpos - ai->xai_InPos, 0, ai);
  1470.  
  1471.     for(i = ai->xai_LowCyl; !err && i <= ai->xai_HighCyl;)
  1472.     {
  1473.       if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
  1474.       !(err = testDMSTrack(&t, xadMasterBase)))
  1475.       {
  1476.         STRPTR res;
  1477.  
  1478.         if(!(err = DecrunchDMS(&t, ai, xadMasterBase, &res, d)))
  1479.         {
  1480.           if(ai->xai_InPos > dpos->firsttrack) /* skip unusable parts */
  1481.           {
  1482.         if(i == t.TrackNumber)
  1483.         {
  1484.               err = xadHookAccess(XADAC_WRITE, t.UnpackedSize, res, ai); ++i;
  1485.             }
  1486.             else if(t.TrackNumber > i)
  1487.               err = XADERR_ILLEGALDATA;
  1488.           }
  1489.           FreeVec(res);
  1490.         }
  1491.       }
  1492.     }
  1493.   }
  1494.  
  1495.   FreeVec(d);
  1496.   return err;
  1497. }
  1498.  
  1499. /****************************************************************************/
  1500.  
  1501. ASM(void) DMS_Free(REG(a0, struct xadArchiveInfo *ai),
  1502. REG(a6, struct xadMasterBase *xadMasterBase))
  1503. {
  1504.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1505.   struct xadFileInfo *fi, *fi2;
  1506.   struct xadDiskInfo *di, *di2;
  1507.   struct xadTextInfo *ti, *ti2;
  1508.  
  1509.   for(fi = ai->xai_FileInfo; fi; fi = fi2)
  1510.   {
  1511.     fi2 = fi->xfi_Next;
  1512.     xadFreeObjectA(fi, 0);
  1513.   }
  1514.   ai->xai_FileInfo = 0;
  1515.  
  1516.   for(di = ai->xai_DiskInfo; di; di = di2)
  1517.   {
  1518.     di2 = di->xdi_Next;
  1519.     
  1520.     for(ti = di->xdi_TextInfo; ti; ti = ti2)
  1521.     {
  1522.       ti2 = ti->xti_Next;
  1523.       if(ti->xti_Text)
  1524.         FreeVec(ti->xti_Text);
  1525.       xadFreeObjectA(ti, 0);
  1526.     }
  1527.     xadFreeObjectA(di, 0);
  1528.   }
  1529.   ai->xai_DiskInfo = 0;
  1530. }
  1531.  
  1532. /****************************************************************************/
  1533.  
  1534. ASM(BOOL) DMSSFX_RecogData(REG(d0, ULONG size), REG(a0, ULONG *data),
  1535. REG(a6, struct xadMasterBase *xadMasterBase))
  1536. {
  1537.   if(*data == HUNK_HEADER)
  1538.   {
  1539.     if(data[5] == 0x1605 && data[6] == 0x1C24 && data[16] == 0x303C05CD &&
  1540.     data[17] == 0x421B51C8 && data[18] == 0xFFFC47F9)
  1541.       return 1;
  1542.     if(data[10] == 0x24E2 && data[9] == 0x60000006 && data[11] == 0x48E77EFE &&
  1543.     data[12] == 0x24482400 && data[16] == 0x3B61425B)
  1544.       return 1; /* defective 2.04 SFX arcs */
  1545.   }
  1546.   return 0;
  1547. }
  1548.  
  1549. /****************************************************************************/
  1550.  
  1551. ASM(LONG) DMSSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  1552. REG(a6, struct xadMasterBase *xadMasterBase))
  1553. {
  1554.   LONG err;
  1555.   LONG data[3];
  1556.  
  1557.   if(!(err = xadHookAccess(XADAC_READ, 12, data, ai)))
  1558.   {
  1559.     if(!(err = xadHookAccess(XADAC_INPUTSEEK, data[2] == 2 ? 0x537C-12 : 0x58C4-12, 0, ai)))
  1560.       err = DMS_GetInfo(ai, xadMasterBase);
  1561.   }
  1562.  
  1563.   return err;
  1564. }
  1565.  
  1566. /****************************************************************************/
  1567.  
  1568. ASM(BOOL) SDSSFX_RecogData(REG(d0, ULONG size), REG(a0, ULONG *data),
  1569. REG(a6, struct xadMasterBase *xadMasterBase))
  1570. {
  1571.   if(*data == HUNK_HEADER)
  1572.   {
  1573.     if(data[15] == 0xFDD823C0 && data[17] == 0x2C404EAE &&
  1574.     data[19] == 0x405A && data[20] == 0x207C0000 && data[21] == 0x020C7600)
  1575.       return 1;
  1576.   }
  1577.   return 0;
  1578. }
  1579.  
  1580. struct SDSSFXData {
  1581.   UBYTE Name[20];
  1582.   ULONG CrSize;
  1583.   ULONG Size;
  1584.   UWORD CheckSum;
  1585. };
  1586.  
  1587. ASM(LONG) SDSSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  1588. REG(a6, struct xadMasterBase *xadMasterBase))
  1589. {
  1590.   LONG err, i, j, num = 1;
  1591.   struct SDSSFXData sd;
  1592.   struct xadFileInfo *fi = 0, *fi2;
  1593.  
  1594.   if((err = xadHookAccess(XADAC_INPUTSEEK, 0x41C, 0, ai)))
  1595.     return err;
  1596.   while(!err)
  1597.   {
  1598.     j = ai->xai_InPos;
  1599.     if(!(err = xadHookAccess(XADAC_READ, sizeof(struct SDSSFXData), &sd, ai)))
  1600.     {
  1601.       if(!(i = strlen(sd.Name)))
  1602.         break; /* last entry */
  1603.       if(!(err = xadHookAccess(XADAC_INPUTSEEK, sd.CrSize, 0, ai)))
  1604.       {
  1605.         if((fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  1606.         XAD_OBJNAMESIZE, i, TAG_DONE)))
  1607.         {
  1608.           fi2->xfi_PrivateInfo = (APTR) j; /* file position */
  1609.           fi2->xfi_Size = sd.Size;
  1610.           fi2->xfi_EntryNumber = num++;
  1611.           fi2->xfi_CrunchSize = sd.CrSize;
  1612.       fi2->xfi_Flags = XADFIF_NODATE;
  1613.           for(j = 0; j < i; ++j)
  1614.             fi2->xfi_FileName[j] = sd.Name[j];
  1615.           err = xadConvertDates(XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
  1616.           &fi2->xfi_Date, TAG_DONE);
  1617.           if(fi)
  1618.             fi->xfi_Next = fi2;
  1619.           else
  1620.             ai->xai_FileInfo = fi2;
  1621.           fi = fi2;
  1622.         }
  1623.         else
  1624.           err = XADERR_NOMEMORY;
  1625.       }
  1626.     }
  1627.   }
  1628.   if(err)
  1629.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  1630.  
  1631.   return fi ? 0 : XADERR_ILLEGALDATA;
  1632. }
  1633.  
  1634. struct DMSDataShort {
  1635.   ULONG        bitbuf;
  1636.   STRPTR    indata;
  1637.   UBYTE        bitcount;
  1638.   UBYTE        DidInit;
  1639.   UWORD        RTV_Medium;
  1640.   UBYTE        Text[32768];
  1641. };
  1642.  
  1643. ASM(LONG) SDSSFX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  1644. REG(a6, struct xadMasterBase *xadMasterBase))
  1645. {
  1646.   struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
  1647.   LONG err;
  1648.   struct SDSSFXData sd;
  1649.  
  1650.   if(ai->xai_InPos != (ULONG) ai->xai_CurFile->xfi_PrivateInfo)
  1651.   {
  1652.     if((err = xadHookAccess(XADAC_INPUTSEEK, ((ULONG) ai->xai_CurFile->xfi_PrivateInfo) -
  1653.     ai->xai_InPos, 0, ai)))
  1654.       return err;
  1655.   }
  1656.   if(!(err = xadHookAccess(XADAC_READ, sizeof(struct SDSSFXData), &sd, ai)))
  1657.   {
  1658.     struct DMSData *d;
  1659.     
  1660.     if((d = (struct DMSData *) AllocMem(sizeof(struct DMSDataShort), MEMF_PUBLIC|MEMF_CLEAR)))
  1661.     {
  1662.       STRPTR buf;
  1663.  
  1664.       if((buf = (STRPTR) AllocVec(sd.CrSize, MEMF_PUBLIC)))
  1665.       {
  1666.         d->RTV_Medium = 0x3FBE;
  1667.  
  1668.         if(!(err = xadHookAccess(XADAC_READ, sd.CrSize, buf, ai)))
  1669.         {
  1670.           if(!(err = DMSUnpMEDIUM(&buf, sd.Size, d, SysBase)))
  1671.           {
  1672.             if(CheckSumDMS(buf, sd.Size) == sd.CheckSum)
  1673.               err = xadHookAccess(XADAC_WRITE, sd.Size, buf, ai);
  1674.             else
  1675.               err = XADERR_CHECKSUM;
  1676.           }
  1677.         }
  1678.         FreeVec(buf);
  1679.       }
  1680.       else
  1681.         err = XADERR_NOMEMORY;
  1682.     }
  1683.     else
  1684.       err = XADERR_NOMEMORY;
  1685.   }
  1686.  
  1687.   return err;
  1688. }
  1689.  
  1690. /****************************************************************************/
  1691.  
  1692. struct xadClient SDSSFX_Client = {
  1693. NEXTCLIENT, XADCLIENT_VERSION, 1, SDSSFX_VERSION, SDSSFX_REVISION, 100,
  1694. XADCF_FILEARCHIVER, XADCID_SDSSFX, "SDS Software SFX",
  1695. (BOOL (*)()) SDSSFX_RecogData, (LONG (*)()) SDSSFX_GetInfo, (LONG (*)())
  1696. SDSSFX_UnArchive, (void (*)()) DMS_Free};
  1697.  
  1698. struct xadClient DMSSFX_Client = {
  1699. &SDSSFX_Client, XADCLIENT_VERSION, 1, DMSSFX_VERSION, DMSSFX_REVISION, 100,
  1700. XADCF_DISKARCHIVER|XADCF_FILEARCHIVER, XADCID_DMSSFX, "DMS SFX",
  1701. (BOOL (*)()) DMSSFX_RecogData, (LONG (*)()) DMSSFX_GetInfo, (LONG (*)())
  1702. DMS_UnArchive, (void (*)()) DMS_Free};
  1703.  
  1704. struct xadClient DMS_Client = {
  1705. &DMSSFX_Client, XADCLIENT_VERSION, 1, DMS_VERSION, DMS_REVISION, sizeof(struct DMSHeader),
  1706. XADCF_DISKARCHIVER|XADCF_FILEARCHIVER, XADCID_DMS, "DMS",
  1707. (BOOL (*)()) DMS_RecogData, (LONG (*)()) DMS_GetInfo, (LONG (*)())
  1708. DMS_UnArchive, (void (*)()) DMS_Free};
  1709.  
  1710. #endif /* XADASTER_DMS_C */
  1711.